package cat.joronya.supermanager.service;

import java.io.ByteArrayOutputStream;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.HTTP;
import org.htmlcleaner.ContentNode;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;

import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.util.Log;
import cat.joronya.supermanager.Supermanager;
import cat.joronya.supermanager.market.Player;

/**
 * Recuperem el llistat de jugadors del mercat.
 * 
 * @author pol
 */
public class MarketSync extends Object//AsyncTask<String,Void,Integer>
{
	private static final String TAG = "supermanager";
	
	// el service
	private SupermanagerService service;
	
	// el client http on fer les peticions
	private DefaultHttpClient client = null;
	
	// jornada passada de loginSyn pq no es a les pagines de market
	private Integer jornada = null;
	
	// status de retorn
	public int status = -1;
	
	// market GET
	private static final String MARKET_GET = InitSync.BASE_URL+"/vermercado.php";
	
	// XPATHs per treure dades de les pagines
	// private leagues XPATH
	private static final String PLAYERS_XPATH = "//table[@background='gif/fondomercado3arriba.gif']";
	
	// dades extretes de les pagines
	public ArrayList<Player> guards;
	public ArrayList<Player> forwards;
	public ArrayList<Player> centers;
	
	/**
	 * Constructor amb el intentService que el crida.
	 * @param intentService
	 */
	public MarketSync(SupermanagerService service, DefaultHttpClient client, Integer jornada)
	{
		this.service = service;
		this.client = client;
		this.jornada = jornada;
		
		this.guards = new ArrayList<Player>();
		this.forwards = new ArrayList<Player>();
		this.centers = new ArrayList<Player>();
	}
	
	protected void execute()//doInBackground(String... params) 
	{
		try
		{
			// position 1 = bases
			execute(1);
			// position 2 = aleros
			execute(2);
			// position 3 = pivots
			execute(3);

			// parsejat ok
	        status = Supermanager.MARKET_PARSED_OK;
	        Log.d(TAG, "MArketSync status: MARKET_PARSED_OK - "+status);
	        return;
		}
		catch(ConnectivityException ce){
			// error de connectivitat
			status = Supermanager.CONNECTIVITY_ERROR_STATUS;
	        Log.d(TAG, "MArketSync status: CONNECTIVITY_ERROR_STATUS - "+status);
			return;
		}
		catch(Exception e){
			// altre error, notifiquem i anem offline
			status = Supermanager.OTHER_ERROR_STATUS;
	        Log.d(TAG, "MArketSync status: OTHER_ERROR_STATUS - "+status);
			return;
		}
	}
	
	@SuppressWarnings("rawtypes")
	private void execute(int position)
		throws ConnectivityException, Exception
	{
		// checkejem per connectivitat
		ConnectivityManager cm = (ConnectivityManager) service.getSystemService(Context.CONNECTIVITY_SERVICE);
		boolean online = cm.getActiveNetworkInfo().isConnectedOrConnecting();

		if( !online )
			throw new ConnectivityException();

		HttpGet plHttpGet = new HttpGet(MARKET_GET+"?id_pos="+position);
		HttpResponse response = client.execute(plHttpGet);
		HtmlCleaner cleaner = new HtmlCleaner();

		ByteArrayOutputStream os = new ByteArrayOutputStream();
		response.getEntity().writeTo(os);
		String marketPage = os.toString(HTTP.ISO_8859_1);
		TagNode node = cleaner.clean(marketPage);

		NumberFormat nf = NumberFormat.getInstance(new Locale("es","ES"));

		// cerquem les lligues
		Object[] table = node.evaluateXPath(PLAYERS_XPATH);
		TagNode tagTable = (TagNode)table[0];
		TagNode tagTbody = tagTable.getChildTags()[0];
		// llistem els equips, diferents trs
		int i=0;
		for(Object objTr: tagTbody.getChildren())
		{
			// descartem dos primers tr dels headers
			if( i++ < 2 )
				continue;

			// els tds
			List tds = ((TagNode)objTr).getChildren();

			// inicialitzem player
			Player p = new Player();
			
			// setejem la jornada
			p.setDay(jornada);

			// segon td
			TagNode td1 = (TagNode)tds.toArray()[1];
			for(Object td1Child: td1.getChildren())
			{
				TagNode img = (TagNode)td1Child;
				if( "img".equals(img.getName()) )
				{
					String src = img.getAttributeByName("src");
					if( "gif/lesion.gif".equals(src) )
						p.setStatus("lesio.png");
					//TODO: comprovar el boto vermell no disponible

					break;
				}
			}

			// tercer td
			TagNode td2 = (TagNode)tds.toArray()[2];
			for(Object td2Child: td2.getChildren())
			{
				TagNode img = (TagNode)td2Child;
				if( "img".equals(img.getName()) )
				{
					String src = img.getAttributeByName("src");
					if( "gif/nacional.gif".equals(src) )
						p.setNacionality("nacional.png");
					if( "gif/extra.gif".equals(src) )
						p.setNacionality("extra.png");

					break;
				}
			}

			// quart td
			TagNode td3 = (TagNode)tds.toArray()[3];
			for(Object td3Child: td3.getChildren())
			{
				TagNode a = (TagNode)td3Child;
				if( "a".equals(a.getName()) )
				{
					String href = a.getAttributeByName("href");
					String cod = href.replace("http://www.acb.com/stspartidojug.php?cod_jugador=", "");
					p.setId(cod);
					Log.d(TAG,"MarketSync parsing code player: "+cod+", jornada: "+jornada);

					for(Object aChild: a.getChildren())
					{
						TagNode font = (TagNode)aChild;
						if( "font".equals(font.getName()) )
						{
							for(Object fontChild: font.getChildren())
							{
								if( fontChild instanceof ContentNode )
								{
									String name = fontChild.toString();
									p.setName(name);
									break;
								}
							}
							break;
						}
					}
					break;
				}
			}

			// cinque td
			TagNode td4 = (TagNode)tds.toArray()[4];
			for(Object td4Child: td4.getChildren())
			{
				// saltem espais inicials
				if( td4Child instanceof ContentNode )
					continue;

				TagNode a = (TagNode)td4Child;
				if( "a".equals(a.getName()) )
				{
					String on = a.getAttributeByName("onMouseover");
					String info = on.replace("ddrivetip('", "").replace("')", "");
					p.setInfo(info);

					break;
				}
			}

			// sise td
			TagNode td5 = (TagNode)tds.toArray()[5];
			for(Object td5Child: td5.getChildren())
			{
				if( td5Child instanceof ContentNode )
				{
					String team = td5Child.toString().trim();
					p.setTeam(team);
					break;
				}
			}

			// sete td
			TagNode td6 = (TagNode)tds.toArray()[6];
			for(Object td6Child: td6.getChildren())
			{
				if( td6Child instanceof ContentNode )
				{
					String balance = td6Child.toString().trim();
					p.setBalance(balance);
					break;
				}
			}

			// vuite td
			TagNode td7 = (TagNode)tds.toArray()[7];
			for(Object td7Child: td7.getChildren())
			{
				if( td7Child instanceof ContentNode )
				{
					Float average;
					try{
						average = Float.valueOf(nf.parse(td7Child.toString().trim()).floatValue());
					}catch(ParseException pe){
						average = Float.valueOf("0");
					}

					p.setAverage(average);
					break;
				}
			}

			// nove td
			TagNode td8 = (TagNode)tds.toArray()[8];
			for(Object td8Child: td8.getChildren())
			{
				if( td8Child instanceof ContentNode )
				{
					Integer price;
					try{
						price = Integer.valueOf(nf.parse(td8Child.toString().trim()).intValue());
					}catch(ParseException pe){
						price = Integer.valueOf(0);
					}
					p.setPrice(price);
					break;
				}
			}

			// dese td
			TagNode td9 = (TagNode)tds.toArray()[9];
			for(Object td9Child: td9.getChildren())
			{
				if( td9Child instanceof ContentNode )
				{
					String minutes = td9Child.toString().trim();
					p.setMinutes(minutes);
					break;
				}
			}

			// onze td
			TagNode td10 = (TagNode)tds.toArray()[10];
			for(Object td10Child: td10.getChildren())
			{
				if( td10Child instanceof ContentNode )
				{
					Float rating;
					try{
						rating = Float.valueOf(nf.parse(td10Child.toString().trim()).floatValue());
					}catch(ParseException pe){
						rating = Float.valueOf("0");
					}
					p.setRating(rating);
					break;
				}
			}

			// dotze td
			TagNode td11 = (TagNode)tds.toArray()[11];
			for(Object td11Child: td11.getChildren())
			{
				if( td11Child instanceof ContentNode )
				{
					Float ratingLast3Games;
					try{
						ratingLast3Games = Float.valueOf(nf.parse(td11Child.toString().trim()).floatValue());
					}catch(ParseException pe){
						ratingLast3Games = Float.valueOf("0");
					}
					p.setRatingLast3Games(ratingLast3Games);
					break;
				}
			}

			// tretze td
			TagNode td12 = (TagNode)tds.toArray()[12];
			for(Object td12Child: td12.getChildren())
			{
				if( td12Child instanceof ContentNode )
				{
					Float increase15;
					try{
						increase15 = Float.valueOf(nf.parse(td12Child.toString().trim()).floatValue());
					}catch(ParseException pe){
						increase15 = Float.valueOf("0");
					}
					p.setIncrease15(increase15);
					break;
				}
			}

			// catorze td
			TagNode td13 = (TagNode)tds.toArray()[13];
			for(Object td13Child: td13.getChildren())
			{
				if( td13Child instanceof ContentNode )
				{
					Float keepPrice;
					try{
						keepPrice = Float.valueOf(nf.parse(td13Child.toString().trim()).floatValue());
					}catch(ParseException pe){
						keepPrice = Float.valueOf("0");
					}
					p.setKeepPrice(keepPrice);
					break;
				}
			}

			// quinze td
			TagNode td14 = (TagNode)tds.toArray()[14];
			for(Object td14Child: td14.getChildren())
			{
				if( td14Child instanceof ContentNode )
				{
					Float decrease15;
					try{
						decrease15 = Float.valueOf(nf.parse(td14Child.toString().trim()).floatValue());
					}catch(ParseException pe){
						decrease15 = Float.valueOf("0");
					}
					p.setDecrease15(decrease15);
					break;
				}
			}

			switch(position)
			{
			case 1:
				p.setPosition(Supermanager.GUARD_POSITION);
				// guardem el player al llistat
				this.guards.add(p);
				break;
			case 2:
				p.setPosition(Supermanager.FORWARD_POSITION);
				// guardem el player al llistat
				this.forwards.add(p);
				break;
			case 3:
			default:
				p.setPosition(Supermanager.CENTER_POSITION);
				// guardem el player al llistat
				this.centers.add(p);
				break;
			}
		}
    }
	
	/**
	 * Guardar les dades trobades a DB.
	 */
    protected void onPostExecute(Uri uri) 
    {
    	// tractem cada jugador, bases
    	Log.d(TAG,"Parsed "+guards.size()+" guard players, going to insert");
    	for(Player p: this.guards)
    	{
    		// insert or update el player al market
    		insertOrUpdatePlayer(uri, p, Supermanager.GUARD_POSITION);
    	}
    	
    	// tractem cada jugador, alers
    	Log.d(TAG,"Parsed "+forwards.size()+" forward players, going to insert");
    	for(Player p: this.forwards)
    	{
    		// insert or update el player al market
    		insertOrUpdatePlayer(uri, p, Supermanager.FORWARD_POSITION);
    	}
    	
    	// tractem cada jugador, pivots
    	Log.d(TAG,"Parsed "+centers.size()+" center players, going to insert");
    	for(Player p: this.centers)
    	{
    		// insert or update el player al market
    		insertOrUpdatePlayer(uri, p, Supermanager.CENTER_POSITION);
    	}	
    }
    
    /**
	 * Insert or Update Player as needed.
	 * @param uri
	 * @param pl
	 * @return
	 */
	private String insertOrUpdatePlayer(Uri uri, Player p, String position)
	{
		// insertem player
		ContentValues values = new ContentValues();
		values.put(Supermanager.Market.ID_PLAYER, p.getId());
		values.put(Supermanager.Market.POSITION, position);
		values.put(Supermanager.Market.DAY, p.getDay());
		values.put(Supermanager.Market.STATUS, p.getStatus());
		values.put(Supermanager.Market.NACIONALITY, p.getNacionality());
		values.put(Supermanager.Market.NAME, p.getName());
		values.put(Supermanager.Market.INFO, p.getInfo());
		values.put(Supermanager.Market.TEAM, p.getTeam());
		values.put(Supermanager.Market.BALANCE, p.getBalance());
		values.put(Supermanager.Market.AVERAGE, p.getAverage());
		values.put(Supermanager.Market.PRICE, p.getPrice());
		values.put(Supermanager.Market.MINUTES, p.getMinutes());
		values.put(Supermanager.Market.RATING, p.getRating());
		values.put(Supermanager.Market.RATING_LAST3_GAMES, p.getRatingLast3Games());
		values.put(Supermanager.Market.INCREASE_15, p.getIncrease15());
		values.put(Supermanager.Market.KEEP_PRICE, p.getKeepPrice());
		values.put(Supermanager.Market.DECREASE_15, p.getDecrease15());
		
		Uri playerUri = Supermanager.Market.CONTENT_URI;
		String lastPathSegment = "0";
		
		// si update no retorna 1 reg, llavors insert
		if( service.getContentResolver().update(uri, 
				values, 
				Supermanager.Market.ID_PLAYER+" = ? AND "+
				Supermanager.Market.DAY+" = ? ", 
				new String[]{p.getId(),p.getDay().toString()}) == 0 )
		{
			playerUri = service.getContentResolver().insert(uri, values);
			lastPathSegment = playerUri.getLastPathSegment();
			Log.d(TAG, "Inserting player [" + p.getName()
					+ "] with Uri [" + playerUri + "] lastPathSegment ["
					+ lastPathSegment + "]");
		}
		else
		{
			Cursor cursor = service.getContentResolver().
				query(Supermanager.Market.CONTENT_URI, 
					  Supermanager.Market.PROJECTION, 
					  Supermanager.Market.ID_PLAYER+" = ? AND "+
					  Supermanager.Market.DAY+" = ? ", 
					  new String[]{p.getId(),p.getDay().toString()}, 
					  Supermanager.Market.DEFAULT_SORT_ORDER);
			
			if( cursor.moveToFirst() )
			{
				lastPathSegment = ""+cursor.getLong(0);
				playerUri = ContentUris.withAppendedId(Supermanager.Market.CONTENT_URI, cursor.getLong(0));
			}
			Log.d(TAG, "Updating player [" + p.getName()
					+ "] with Uri [" + playerUri + "] lastPathSegment ["
					+ lastPathSegment + "]");
		}
		
		return lastPathSegment;
	}
}	
